/*
 *  libzplay - windows ( WIN32 ) multimedia library
 *
 *  ver: 2.00
 *  date: 22. April, 2010.
 *
 *  Copyright (C) 2003-2010 Zoran Cindori
 *
 *  Author: Zoran Cindori
 *  Web: http://libzplay.sourceforge.net/
 *  Email: zcindori@inet.hr
 *
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 *
 *
 * Supported by:
 *
 * ============================================================================
 * libmad - MPEG audio decoder library
 * Copyright (C) 2000-2004 Underbit Technologies, Inc. <support@underbit.com>
 * http://www.underbit.com/products/mad/
 * GNU General Public License ( GPL.TXT )
 * ============================================================================
 * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2002 
 * by the Xiph.Org Foundation http://www.xiph.org/
 * BSD-STYLE SOURCE LICENSE  ( XIPH.TXT )
 * ============================================================================
 * LIBA52
 * free library for decoding ATSC A/52 streams.
 * It is released under the terms of the GPL license.
 * ============================================================================
 * FLAC - Free Lossless Audio Codec
 * Copyright (C) 2001,2002,2003,2004,2005,2006,2007  Josh Coalson
 * http://flac.sourceforge.net/
 *
 * This file is part the FLAC project.  FLAC is comprised of several
 * components distributed under difference licenses.  The codec libraries
 * are distributed under Xiph.Org's BSD-like license (see the file
 * XIPH.TXT in this distribution).  All other programs, libraries, and
 * plugins are distributed under the LGPL or GPL (see LGPL.TXT and
 * GPL.TXT).  The documentation is distributed under the Gnu FDL (see
 * FDL.TXT).  Each file in the FLAC distribution contains at the top the
 * terms under which it may be distributed.
 *
 * Since this particular file is relevant to all components of FLAC,
 * it may be distributed under the Xiph.Org license, which is the least
 * restrictive of those mentioned above.  See the file XIPH.TXT in this
 * distribution.
 * ============================================================================
 * FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding
 * Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 *
 * Any non-GPL usage of this software or parts of this software is strictly
 * forbidden.
 *
 * The "appropriate copyright message" mentioned in section 2c of the GPLv2
 * must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com"
 *
 * Commercial non-GPL licensing of this software is possible.
 * For more info contact Nero AG through Mpeg4AAClicense@nero.com.
 *
 * ============================================================================
 * FAAC - Freeware Advanced Audio Coder Copyright (C) 2001 M. Bakker
 * This library is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as published by the
 * Free Software Foundation; either version 2.1 of the License, or
 * (at your option) any later version. 
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Lesser General Public License for more details. 
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this library; if not, write to the Free Software Foundation,
 * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 
 *
 * ============================================================================
 * libmp3lame encoder
 * LAME 3.xx LAME Ain't an MP3 Encoder http://www.mp3dev.org March 2001 
 * 
 * Originally developed by Mike Cheng (www.uq.net.au/~zzmcheng).
 * Now maintained by Mark Taylor (www.mp3dev.org). 
 *
 * This code is distributed under the GNU LESSER PUBLIC LICENSE (LGPL, see www.gnu.org)
 * with the following modification: 
 * 
 * If you determine that distribution of LAME requires a patent license,
 * and you obtain a patent license, you may distribute LAME even though redistribution
 * of LAME may also require a patent license. 
 *
 * You agree not to enforce any patent claims for any aspect of MPEG audio compression,
 * or any other techniques contained in the LAME source code. 
 *
 * Copyrights (c) 1999-1007 by The LAME Project Copyrights (c) 1999,2000,2001
 * by Mark Taylor Copyrights (c) 1999,2000,2001 by Mark Taylor Copyrights
 * (c) 1998 by Michael Cheng Copyrights (c) 1995,1996,1997 by Michael Hipp: mpglib
 *
 * ============================================================================
 * SoundTouch library Copyright (c) Olli Parviainen 2002-2009 
 * http://www.surina.net/soundtouch
 * GNU Lesser General Public License vesrion 2.1 (LGPL.TXT )
 * ============================================================================
 * Center Cut DSP Plugin for Winamp 2.x 
 * Copyright (C) 2004  Moitah (moitah@yahoo.com)
 * GNU General Public License ( GPL.TXT )
 * ============================================================================
 * Shibatch Super Equalizer ver 0.03 for winamp
 * written by Naoki Shibata  shibatch@users.sourceforge.net
 * http://shibatch.sourceforge.net/
 *
 * Shibatch Super Equalizer (except FFT part) is distributed under LGPL.
 * See LGPL.txt for details.
 * FFT part is a routine made by Mr.Ooura. This routine is a freeware.
 * Contact Mr.Ooura for details of distributing licenses.
 * http://momonga.t.u-tokyo.ac.jp/~ooura/fft.html
 * ============================================================================
 * The Independent JPEG Group's JPEG software
 * JPEG decoding library
 * Copyright (C) 1991-2010, Thomas G. Lane, Guido Vollbeding.
 * www.ijg.org
 * ============================================================================
 * ZLIB DATA COMPRESSION LIBRARY
 * (C) 1995-2010 Jean-loup Gailly and Mark Adler
 * http://zlib.net/ 
 * ============================================================================
 * libpng library
 * PNG picture decoding library
 * Copyright (c) 2004, 2006-2007 Glenn Randers-Pehrson
 * http://www.libpng.org/
 * ============================================================================
*/



using namespace System;
using namespace System::Runtime::InteropServices;
using namespace System::Drawing;


namespace libZPlay
{

#pragma region Structure and Enum
 
    public enum class TSettingID: int
    {
        sidWaveBufferSize = 1,
        sidAccurateLength = 2,
        sidAccurateSeek = 3,
        sidSamplerate = 4,
        sidChannelNumber = 5,
        sidBitPerSample = 6,
        sidBigEndian = 7
    };

    public enum class TStreamFormat: int
    {
        sfUnknown = 0,
        sfMp3 = 1,
        sfOgg = 2,
        sfWav = 3,
        sfPCM = 4,
        sfFLAC = 5,
		sfFLACOgg = 6,
		sfAC3 = 7,
		sfAacADTS = 8,
		sfWaveIn = 9,
        sfAutodetect = 1000
    };


    [StructLayout(LayoutKind::Explicit)]
    public value class TStreamHMSTime
    {
    public:
        [FieldOffset(0)]
        System::UInt32 hour;
        [FieldOffset(4)]
        System::UInt32 minute;
        [FieldOffset(8)]
        System::UInt32 second;
        [FieldOffset(12)]
        System::UInt32 millisecond;
    };

    [StructLayout(LayoutKind::Explicit)]
    public value class TStreamTime
    {
    public:
        [FieldOffset(0)]
        System::UInt32 sec;
        [FieldOffset(4)]
        System::UInt32 ms;
        [FieldOffset(8)]
        System::UInt32 samples;
        [FieldOffset(12)]
        TStreamHMSTime hms;
    };

    [StructLayout(LayoutKind::Explicit, CharSet=CharSet::Unicode)]
    public value class TStreamInfo
    {
    public:
        [FieldOffset(0)]
        int SamplingRate;
        [FieldOffset(4)]
        int ChannelNumber;
        [FieldOffset(8)]
        bool VBR;
        [FieldOffset(12)]
        int Bitrate;
        [FieldOffset(16)]
        TStreamTime Length;
        [FieldOffset(44)]
        System::String ^Description;
    };



    [StructLayout(LayoutKind::Explicit, CharSet=CharSet::Unicode)]
    public value class TWaveOutInfo
    {
    public:
        [FieldOffset(0)]
        System::UInt32 ManufacturerID;
        [FieldOffset(4)]
        System::UInt32 ProductID;
        [FieldOffset(8)]
        System::UInt32 DriverVersion;
        [FieldOffset(12)]
        System::UInt32 Formats;
        [FieldOffset(16)]
        System::UInt32 Channels;
        [FieldOffset(20)]
        System::UInt32 Support;
        [FieldOffset(24)]
        System::String ^ProductName;
    };

	   [StructLayout(LayoutKind::Explicit, CharSet=CharSet::Unicode)]
    public value class TWaveInInfo
    {
    public:
        [FieldOffset(0)]
        System::UInt32 ManufacturerID;
        [FieldOffset(4)]
        System::UInt32 ProductID;
        [FieldOffset(8)]
        System::UInt32 DriverVersion;
        [FieldOffset(12)]
        System::UInt32 Formats;
        [FieldOffset(16)]
        System::UInt32 Channels;
        [FieldOffset(20)]
        System::String ^ProductName;
    };


    public enum class TFFTWindow: int
    {
        fwRectangular = 1,
        fwHamming,
        fwHann,
        fwCosine,
        fwLanczos,
        fwBartlett,
        fwTriangular,
        fwGauss,
        fwBartlettHann,
        fwBlackman,
        fwNuttall,
        fwBlackmanHarris,
        fwBlackmanNuttall,
        fwFlatTop
    };




    public enum class TTimeFormat: System::UInt32
    {
        tfMillisecond = 1,
        tfSecond = 2,
        tfHMS = 4,
        tfSamples = 8
    };

    public enum class TSeekMethod: int
    {
        smFromBeginning = 1,
        smFromEnd = 2,
        smFromCurrentForward = 4,
        smFromCurrentBackward = 8
    };

    [StructLayout(LayoutKind::Explicit)]
    public value class TStreamLoadInfo
    {
    public:
        [FieldOffset(0)]
        System::UInt32 NumberOfBuffers;
        [FieldOffset(4)]
        System::UInt32 NumberOfBytes;
    };




    [StructLayout(LayoutKind::Explicit)]
    public value class TEchoEffect
    {
    public:
        [FieldOffset(0)]
        int nLeftDelay;
        [FieldOffset(4)]
        int nLeftSrcVolume;
        [FieldOffset(8)]
        int nLeftEchoVolume;
        [FieldOffset(12)]
        int nRightDelay;
        [FieldOffset(16)]
        int nRightSrcVolume;
        [FieldOffset(20)]
        int nRightEchoVolume;
    };

    public enum class TID3Version: int
    {
        id3Version1 = 1,
        id3Version2 = 2
    };


    public enum class TFFTGraphHorizontalScale: int
    {
        gsLogarithmic = 0,
        gsLinear = 1
    };

    public enum class TFFTGraphParamID: int
    {
        gpFFTPoints = 1,
        gpGraphType,
        gpWindow,
        gpHorizontalScale,
        gpSubgrid,
        gpTransparency,
		gpFrequencyScaleVisible,
		gpDecibelScaleVisible,
		gpFrequencyGridVisible,
		gpDecibelGridVisible,
		gpBgBitmapVisible,
		gpBgBitmapHandle,
		gpColor1,
		gpColor2,
		gpColor3,
		gpColor4,
		gpColor5,
		gpColor6,
		gpColor7,
		gpColor8,
		gpColor9,
		gpColor10,
		gpColor11,
		gpColor12,
		gpColor13,
		gpColor14,
		gpColor15,
		gpColor16
    };

    public enum class TFFTGraphType: int
    {
        gtLinesLeftOnTop = 0,
        gtLinesRightOnTop,
        gtAreaLeftOnTop,
        gtAreaRightOnTop,
        gtBarsLeftOnTop,
        gtBarsRightOnTop,
		gtSpectrum
    };



    [StructLayout(LayoutKind::Explicit)]
    public value class TStreamStatus
    {
    public:
        [FieldOffset(0)]
        bool fPlay;
        [FieldOffset(4)]
        bool fPause;
        [FieldOffset(8)]
        bool fEcho;
        [FieldOffset(12)]
        bool fEqualizer;
        [FieldOffset(16)]
        bool fVocalCut;
        [FieldOffset(20)]
        bool fSideCut;
        [FieldOffset(24)]
        bool fChannelMix;
        [FieldOffset(28)]
        bool fSlideVolume;
        [FieldOffset(32)]
        int nLoop;
        [FieldOffset(36)]
        bool fReverse;
        [FieldOffset(40)]
        int nSongIndex;
        [FieldOffset(44)]
        int nSongsInQueue;
    };


    


    [StructLayout(LayoutKind::Explicit, CharSet=CharSet::Unicode)]
    public value class TID3Info
    {
    public:
        [FieldOffset(0)]
        System::String ^Title;
        [FieldOffset(4)]
        System::String ^Artist;
        [FieldOffset(8)]
        System::String ^Album;
        [FieldOffset(12)]
        System::String ^Year;
        [FieldOffset(16)]
        System::String ^Comment;
        [FieldOffset(20)]
        System::String ^Track;
        [FieldOffset(24)]
        System::String ^Genre;
    };

	 public value class TID3Picture
   {

	public:
		bool PicturePresent;
		int PictureType;
		System::String ^Description;
		Bitmap ^Bitmap;
		System::IO::MemoryStream ^BitStream;
	};

	public value class TID3InfoEx
	{
	public:
		System::String ^Title;
		System::String ^Artist;
		System::String ^Album;
		System::String ^Year;
		System::String ^Comment;
		System::String ^Track;
		System::String ^Genre;
		System::String ^AlbumArtist;
		System::String ^Composer;
		System::String ^OriginalArtist;
		System::String ^Copyright;
		System::String ^URL;
		System::String ^Encoder;
		System::String ^Publisher;
		int BPM;
		TID3Picture Picture;
	};


    public enum class TBPMDetectionMethod: int
    {
        dmPeaks = 0,
        dmAutoCorrelation
    };


    public enum class TFFTGraphSize: int
    {
        FFTGraphMinWidth = 100,
        FFTGraphMinHeight = 60
    };

    public enum class TWaveOutMapper: System::UInt32
    {
        WaveOutWaveMapper = 4294967295
    };

	public enum class TWaveInMapper: System::UInt32
    {
        WaveInWaveMapper = 4294967295
    };

    public enum class TCallbackMessage: int
    {
        MsgStopAsync = 1,
        MsgPlayAsync = 2,
        MsgEnterLoopAsync = 4,
        MsgExitLoopAsync = 8,
        MsgEnterVolumeSlideAsync = 16,
        MsgExitVolumeSlideAsync = 32,
        MsgStreamBufferDoneAsync = 64,
        MsgStreamNeedMoreDataAsync = 128,
        MsgNextSongAsync = 256,
        MsgStop = 65536,
        MsgPlay = 131072,
        MsgEnterLoop = 262144,
        MsgExitLoop = 524288,
        MsgEnterVolumeSlide = 1048576,
        MsgExitVolumeSlide = 2097152,
        MsgStreamBufferDone = 4194304,
        MsgStreamNeedMoreData = 8388608,
        MsgNextSong = 16777216,
        MsgWaveBuffer = 33554432
    };


    public enum class TWaveOutFormat: System::UInt32
    {
        format_invalid = 0,
        format_11khz_8bit_mono = 1,
        format_11khz_8bit_stereo = 2,
        format_11khz_16bit_mono = 4,
        format_11khz_16bit_stereo = 8,

        format_22khz_8bit_mono = 16,
        format_22khz_8bit_stereo = 32,
        format_22khz_16bit_mono = 64,
        format_22khz_16bit_stereo = 128,

        format_44khz_8bit_mono = 256,
        format_44khz_8bit_stereo = 512,
        format_44khz_16bit_mono = 1024,
        format_44khz_16bit_stereo = 2048
    };

    public enum class TWaveOutFunctionality: System::UInt32
    {
        supportPitchControl = 1,
        supportPlaybackRateControl = 2,
        supportVolumeControl = 4,
        supportSeparateLeftRightVolume = 8,
        supportSync = 16,
        supportSampleAccuratePosition = 32,
        supportDirectSound = 6
    };


	[StructLayout(LayoutKind::Explicit, CharSet=CharSet::Unicode)]
    private value class TStreamInfo_Internal
    {
	public:
        [FieldOffset(0)]
        int SamplingRate;
        [FieldOffset(4)]
        int ChannelNumber;
        [FieldOffset(8)]
        bool VBR;
        [FieldOffset(12)]
        int Bitrate;
        [FieldOffset(16)]
        TStreamTime Length;
        [FieldOffset(44)]
        System::IntPtr Description;
    };



    [StructLayout(LayoutKind::Explicit, CharSet=CharSet::Unicode)]
    private value class TWaveOutInfo_Internal
    {
	public:
        [FieldOffset(0)]
        System::UInt32 ManufacturerID;
        [FieldOffset(4)]
        System::UInt32 ProductID;
        [FieldOffset(8)]
        System::UInt32 DriverVersion;
        [FieldOffset(12)]
        System::UInt32 Formats;
        [FieldOffset(16)]
        System::UInt32 Channels;
        [FieldOffset(20)]
        System::UInt32 Support;
        [FieldOffset(24)]
        System::IntPtr ProductName;
    };


	    [StructLayout(LayoutKind::Explicit, CharSet=CharSet::Unicode)]
    private value class TWaveInInfo_Internal
    {
	public:
        [FieldOffset(0)]
        System::UInt32 ManufacturerID;
        [FieldOffset(4)]
        System::UInt32 ProductID;
        [FieldOffset(8)]
        System::UInt32 DriverVersion;
        [FieldOffset(12)]
        System::UInt32 Formats;
        [FieldOffset(16)]
        System::UInt32 Channels;
        [FieldOffset(20)]
        System::IntPtr ProductName;
    };

	    [StructLayout(LayoutKind::Explicit, CharSet=CharSet::Unicode)]
    private value class TID3Info_Internal
    {
	public:
        [FieldOffset(0)]
        System::IntPtr Title;
        [FieldOffset(4)]
        System::IntPtr Artist;
        [FieldOffset(8)]
        System::IntPtr Album;
        [FieldOffset(12)]
        System::IntPtr Year;
        [FieldOffset(16)]
        System::IntPtr Comment;
        [FieldOffset(20)]
        System::IntPtr Track;
        [FieldOffset(24)]
        System::IntPtr Genre;
    };



	[StructLayout(LayoutKind::Explicit, CharSet=CharSet::Unicode)]
	private value class TID3InfoEx_Internal
	{
		public:
			[FieldOffset(0)]
			IntPtr Title;
			[FieldOffset(4)]
			IntPtr Artist;
			[FieldOffset(8)]
			IntPtr Album;
			[FieldOffset(12)]
			IntPtr Year;
			[FieldOffset(16)]
			IntPtr Comment;
			[FieldOffset(20)]
			IntPtr Track;
			[FieldOffset(24)]
			IntPtr Genre;
			[FieldOffset(28)]
			IntPtr AlbumArtist;
			[FieldOffset(32)]
			IntPtr Composer;
			[FieldOffset(36)]
			IntPtr OriginalArtist;
			[FieldOffset(40)]
			IntPtr Copyright;
			[FieldOffset(44)]
			IntPtr URL;
			[FieldOffset(48)]
			IntPtr Encoder;
			[FieldOffset(52)]
			IntPtr Publisher;
			[FieldOffset(56)]
			int BPM;
			[FieldOffset(60)]
			int PicturePresent;
			[FieldOffset(64)]
			int CanDrawPicture;
			[FieldOffset(68)]
			IntPtr MIMEType;
			[FieldOffset(72)]
			int PictureType;
			[FieldOffset(76)]
			IntPtr Description;
			[FieldOffset(80)]
			IntPtr PictureData;
			[FieldOffset(84)]
			int PictureDataSize;
			[FieldOffset(88)]
			IntPtr hBitmap;
			[FieldOffset(92)]
			int Width;
			[FieldOffset(96)]
			int Height;
			[FieldOffset(356)]
			IntPtr reserved;
		};


#pragma endregion
    public ref class ZPlay
    {

public:
    delegate int TCallbackFunc(System::UInt32 objptr, int user_data, TCallbackMessage msg, System::UInt32 param1, System::UInt32 param2);



#pragma region libzplay.dll interface

    private:


        [System::Runtime::InteropServices::DllImport("libzplay.dll", EntryPoint="zplay_CreateZPlay", ExactSpelling=true, CharSet=System::Runtime::InteropServices::CharSet::Ansi, SetLastError=true)]
        static System::UInt32 zplay_CreateZPlay();

        [System::Runtime::InteropServices::DllImport("libzplay.dll", EntryPoint="zplay_DestroyZPlay", ExactSpelling=true, CharSet=System::Runtime::InteropServices::CharSet::Ansi, SetLastError=true)]
        static int zplay_DestroyZPlay(System::UInt32 objptr);

        [System::Runtime::InteropServices::DllImport("libzplay.dll", EntryPoint="zplay_SetSettings", ExactSpelling=true, CharSet=System::Runtime::InteropServices::CharSet::Ansi, SetLastError=true)]
        static int zplay_SetSettings(System::UInt32 objptr, int nSettingID, int value);

        [System::Runtime::InteropServices::DllImport("libzplay.dll", EntryPoint="zplay_GetSettings", ExactSpelling=true, CharSet=System::Runtime::InteropServices::CharSet::Ansi, SetLastError=true)]
        static int zplay_GetSettings(System::UInt32 objptr, int nSettingID);


        [System::Runtime::InteropServices::DllImport("libzplay.dll", EntryPoint="zplay_GetError", ExactSpelling=true, CharSet=System::Runtime::InteropServices::CharSet::Ansi, SetLastError=true)]
        static IntPtr zplay_GetError(System::UInt32 objptr);

        [System::Runtime::InteropServices::DllImport("libzplay.dll", EntryPoint="zplay_GetErrorW", ExactSpelling=true, CharSet=System::Runtime::InteropServices::CharSet::Unicode, SetLastError=true)]
        static IntPtr zplay_GetErrorW(System::UInt32 objptr);

        [System::Runtime::InteropServices::DllImport("libzplay.dll", EntryPoint="zplay_GetVersion", ExactSpelling=true, CharSet=System::Runtime::InteropServices::CharSet::Ansi, SetLastError=true)]
        static int zplay_GetVersion(System::UInt32 objptr);

        [System::Runtime::InteropServices::DllImport("libzplay.dll", EntryPoint="zplay_GetFileFormat", ExactSpelling=true, CharSet=System::Runtime::InteropServices::CharSet::Ansi, SetLastError=true)]
        static int zplay_GetFileFormat(System::UInt32 objptr, [MarshalAs(UnmanagedType::LPStr)] System::String ^pchFileName);

        [System::Runtime::InteropServices::DllImport("libzplay.dll", EntryPoint="zplay_GetFileFormatW", ExactSpelling=true, CharSet=System::Runtime::InteropServices::CharSet::Unicode, SetLastError=true)]
        static int zplay_GetFileFormatW(System::UInt32 objptr, [MarshalAs(UnmanagedType::LPWStr)] System::String ^pchFileName);

        [System::Runtime::InteropServices::DllImport("libzplay.dll", EntryPoint="zplay_OpenFile", ExactSpelling=true, CharSet=System::Runtime::InteropServices::CharSet::Ansi, SetLastError=true)]
        static int zplay_OpenFile(System::UInt32 objptr, [MarshalAs(UnmanagedType::LPStr)] System::String ^sFileName, int nFormat);

        [System::Runtime::InteropServices::DllImport("libzplay.dll", EntryPoint="zplay_AddFile", ExactSpelling=true, CharSet=System::Runtime::InteropServices::CharSet::Ansi, SetLastError=true)]
        static int zplay_AddFile(System::UInt32 objptr, [MarshalAs(UnmanagedType::LPStr)] System::String ^sFileName, int nFormat);

        [System::Runtime::InteropServices::DllImport("libzplay.dll", EntryPoint="zplay_OpenFileW", ExactSpelling=true, CharSet=System::Runtime::InteropServices::CharSet::Unicode, SetLastError=true)]
        static int zplay_OpenFileW(System::UInt32 objptr, [MarshalAs(UnmanagedType::LPWStr)] System::String ^sFileName, int nFormat);

        [System::Runtime::InteropServices::DllImport("libzplay.dll", EntryPoint="zplay_AddFileW", ExactSpelling=true, CharSet=System::Runtime::InteropServices::CharSet::Unicode, SetLastError=true)]
        static int zplay_AddFileW(System::UInt32 objptr, [MarshalAs(UnmanagedType::LPWStr)] System::String ^sFileName, int nFormat);

        [System::Runtime::InteropServices::DllImport("libzplay.dll", EntryPoint="zplay_OpenStream", ExactSpelling=true, CharSet=System::Runtime::InteropServices::CharSet::Ansi, SetLastError=true)]
        static int zplay_OpenStream(System::UInt32 objptr, int fBuffered, int fManaged, [In()] array<System::Byte> ^sMemStream, System::UInt32 nStreamSize, int nFormat);

        [System::Runtime::InteropServices::DllImport("libzplay.dll", EntryPoint="zplay_PushDataToStream", ExactSpelling=true, CharSet=System::Runtime::InteropServices::CharSet::Ansi, SetLastError=true)]
        static int zplay_PushDataToStream(System::UInt32 objptr, [In()] array<System::Byte> ^sMemNewData, System::UInt32 nNewDataize);


        [System::Runtime::InteropServices::DllImport("libzplay.dll", EntryPoint="zplay_Close", ExactSpelling=true, CharSet=System::Runtime::InteropServices::CharSet::Ansi, SetLastError=true)]
        static int zplay_Close(System::UInt32 objptr);

        [System::Runtime::InteropServices::DllImport("libzplay.dll", EntryPoint="zplay_Play", ExactSpelling=true, CharSet=System::Runtime::InteropServices::CharSet::Ansi, SetLastError=true)]
        static int zplay_Play(System::UInt32 objptr);

        [System::Runtime::InteropServices::DllImport("libzplay.dll", EntryPoint="zplay_Stop", ExactSpelling=true, CharSet=System::Runtime::InteropServices::CharSet::Ansi, SetLastError=true)]
        static int zplay_Stop(System::UInt32 objptr);

        [System::Runtime::InteropServices::DllImport("libzplay.dll", EntryPoint="zplay_Pause", ExactSpelling=true, CharSet=System::Runtime::InteropServices::CharSet::Ansi, SetLastError=true)]
        static int zplay_Pause(System::UInt32 objptr);

        [System::Runtime::InteropServices::DllImport("libzplay.dll", EntryPoint="zplay_Resume", ExactSpelling=true, CharSet=System::Runtime::InteropServices::CharSet::Ansi, SetLastError=true)]
        static int zplay_Resume(System::UInt32 objptr);

        [System::Runtime::InteropServices::DllImport("libzplay.dll", EntryPoint="zplay_IsStreamDataFree", ExactSpelling=true, CharSet=System::Runtime::InteropServices::CharSet::Ansi, SetLastError=true)]
        static int zplay_IsStreamDataFree(System::UInt32 objptr, [In()] array<System::Byte> ^sMemNewData);

        [System::Runtime::InteropServices::DllImport("libzplay.dll", EntryPoint="zplay_GetDynamicStreamLoad", ExactSpelling=true, CharSet=System::Runtime::InteropServices::CharSet::Ansi, SetLastError=true)]
        static void zplay_GetDynamicStreamLoad(System::UInt32 objptr, TStreamLoadInfo %pStreamLoadInfo);

        [System::Runtime::InteropServices::DllImport("libzplay.dll", EntryPoint="zplay_GetPosition", ExactSpelling=true, CharSet=System::Runtime::InteropServices::CharSet::Ansi, SetLastError=true)]
        static void zplay_GetPosition(System::UInt32 objptr, TStreamTime %pTime);

        [System::Runtime::InteropServices::DllImport("libzplay.dll", EntryPoint="zplay_PlayLoop", ExactSpelling=true, CharSet=System::Runtime::InteropServices::CharSet::Ansi, SetLastError=true)]
        static int zplay_PlayLoop(System::UInt32 objptr, int fFormatStartTime, TStreamTime %pStartTime, int fFormatEndTime, TStreamTime %pEndTime, System::UInt32 nNumOfCycles, System::UInt32 fContinuePlaying);

        [System::Runtime::InteropServices::DllImport("libzplay.dll", EntryPoint="zplay_Seek", ExactSpelling=true, CharSet=System::Runtime::InteropServices::CharSet::Ansi, SetLastError=true)]
        static int zplay_Seek(System::UInt32 objptr, TTimeFormat fFormat, TStreamTime %pTime, TSeekMethod nMoveMethod);

        [System::Runtime::InteropServices::DllImport("libzplay.dll", EntryPoint="zplay_ReverseMode", ExactSpelling=true, CharSet=System::Runtime::InteropServices::CharSet::Ansi, SetLastError=true)]
        static int zplay_ReverseMode(System::UInt32 objptr, int fEnable);

        [System::Runtime::InteropServices::DllImport("libzplay.dll", EntryPoint="zplay_SetMasterVolume", ExactSpelling=true, CharSet=System::Runtime::InteropServices::CharSet::Ansi, SetLastError=true)]
        static int zplay_SetMasterVolume(System::UInt32 objptr, int nLeftVolume, int nRightVolume);

        [System::Runtime::InteropServices::DllImport("libzplay.dll", EntryPoint="zplay_SetPlayerVolume", ExactSpelling=true, CharSet=System::Runtime::InteropServices::CharSet::Ansi, SetLastError=true)]
        static int zplay_SetPlayerVolume(System::UInt32 objptr, int nLeftVolume, int nRightVolume);

        [System::Runtime::InteropServices::DllImport("libzplay.dll", EntryPoint="zplay_GetMasterVolume", ExactSpelling=true, CharSet=System::Runtime::InteropServices::CharSet::Ansi, SetLastError=true)]
        static void zplay_GetMasterVolume(System::UInt32 objptr, int %nLeftVolume, int %nRightVolume);

        [System::Runtime::InteropServices::DllImport("libzplay.dll", EntryPoint="zplay_GetPlayerVolume", ExactSpelling=true, CharSet=System::Runtime::InteropServices::CharSet::Ansi, SetLastError=true)]
        static void zplay_GetPlayerVolume(System::UInt32 objptr, int %nLeftVolume, int %nRightVolume);

        [System::Runtime::InteropServices::DllImport("libzplay.dll", EntryPoint="zplay_GetBitrate", ExactSpelling=true, CharSet=System::Runtime::InteropServices::CharSet::Ansi, SetLastError=true)]
        static int zplay_GetBitrate(System::UInt32 objptr, int fAverage);

        [System::Runtime::InteropServices::DllImport("libzplay.dll", EntryPoint="zplay_GetStatus", ExactSpelling=true, CharSet=System::Runtime::InteropServices::CharSet::Ansi, SetLastError=true)]
        static void zplay_GetStatus(System::UInt32 objptr, TStreamStatus %pStatus);

        [System::Runtime::InteropServices::DllImport("libzplay.dll", EntryPoint="zplay_MixChannels", ExactSpelling=true, CharSet=System::Runtime::InteropServices::CharSet::Ansi, SetLastError=true)]
        static int zplay_MixChannels(System::UInt32 objptr, int fEnable, System::UInt32 nLeftPercent, System::UInt32 nRightPercent);

        [System::Runtime::InteropServices::DllImport("libzplay.dll", EntryPoint="zplay_GetVUData", ExactSpelling=true, CharSet=System::Runtime::InteropServices::CharSet::Ansi, SetLastError=true)]
        static void zplay_GetVUData(System::UInt32 objptr, int %pnLeftChannel, int %pnRightChannel);

        [System::Runtime::InteropServices::DllImport("libzplay.dll", EntryPoint="zplay_SlideVolume", ExactSpelling=true, CharSet=System::Runtime::InteropServices::CharSet::Ansi, SetLastError=true)]
        static int zplay_SlideVolume(System::UInt32 objptr, TTimeFormat fFormatStart, TStreamTime %pTimeStart, int nStartVolumeLeft, int nStartVolumeRight, TTimeFormat fFormatEnd, TStreamTime %pTimeEnd, int nEndVolumeLeft, int nEndVolumeRight);

        [System::Runtime::InteropServices::DllImport("libzplay.dll", EntryPoint="zplay_EnableEqualizer", ExactSpelling=true, CharSet=System::Runtime::InteropServices::CharSet::Ansi, SetLastError=true)]
        static int zplay_EnableEqualizer(System::UInt32 objptr, int fEnable);

        [System::Runtime::InteropServices::DllImport("libzplay.dll", EntryPoint="zplay_SetEqualizerPoints", ExactSpelling=true, CharSet=System::Runtime::InteropServices::CharSet::Ansi, SetLastError=true)]
        static int zplay_SetEqualizerPoints(System::UInt32 objptr, [In()] array<int> ^pnFreqPoint, int nNumOfPoints);

        [System::Runtime::InteropServices::DllImport("libzplay.dll", EntryPoint="zplay_GetEqualizerPoints", ExactSpelling=true, CharSet=System::Runtime::InteropServices::CharSet::Ansi, SetLastError=true)]
        static int zplay_GetEqualizerPoints(System::UInt32 objptr, [In(), Out()] array<int> ^pnFreqPoint, int nNumOfPoints);

        [System::Runtime::InteropServices::DllImport("libzplay.dll", EntryPoint="zplay_SetEqualizerParam", ExactSpelling=true, CharSet=System::Runtime::InteropServices::CharSet::Ansi, SetLastError=true)]
        static int zplay_SetEqualizerParam(System::UInt32 objptr, int nPreAmpGain, [In()] array<int> ^pnBandGain, int nNumberOfBands);


        [System::Runtime::InteropServices::DllImport("libzplay.dll", EntryPoint="zplay_GetEqualizerParam", ExactSpelling=true, CharSet=System::Runtime::InteropServices::CharSet::Ansi, SetLastError=true)]
        static int zplay_GetEqualizerParam(System::UInt32 objptr, int %nPreAmpGain, [In(), Out()] array<int> ^pnBandGain, int nNumberOfBands);

        [System::Runtime::InteropServices::DllImport("libzplay.dll", EntryPoint="zplay_SetEqualizerPreampGain", ExactSpelling=true, CharSet=System::Runtime::InteropServices::CharSet::Ansi, SetLastError=true)]
        static int zplay_SetEqualizerPreampGain(System::UInt32 objptr, int nGain);

        [System::Runtime::InteropServices::DllImport("libzplay.dll", EntryPoint="zplay_GetEqualizerPreampGain", ExactSpelling=true, CharSet=System::Runtime::InteropServices::CharSet::Ansi, SetLastError=true)]
        static int zplay_GetEqualizerPreampGain(System::UInt32 objptr);

        [System::Runtime::InteropServices::DllImport("libzplay.dll", EntryPoint="zplay_SetEqualizerBandGain", ExactSpelling=true, CharSet=System::Runtime::InteropServices::CharSet::Ansi, SetLastError=true)]
        static int zplay_SetEqualizerBandGain(System::UInt32 objptr, int nBandIndex, int nGain);

        [System::Runtime::InteropServices::DllImport("libzplay.dll", EntryPoint="zplay_GetEqualizerBandGain", ExactSpelling=true, CharSet=System::Runtime::InteropServices::CharSet::Ansi, SetLastError=true)]
        static int zplay_GetEqualizerBandGain(System::UInt32 objptr, int nBandIndex);

        [System::Runtime::InteropServices::DllImport("libzplay.dll", EntryPoint="zplay_EnableEcho", ExactSpelling=true, CharSet=System::Runtime::InteropServices::CharSet::Ansi, SetLastError=true)]
        static int zplay_EnableEcho(System::UInt32 objptr, int fEnable);

        [System::Runtime::InteropServices::DllImport("libzplay.dll", EntryPoint="zplay_StereoCut", ExactSpelling=true, CharSet=System::Runtime::InteropServices::CharSet::Ansi, SetLastError=true)]
        static int zplay_StereoCut(System::UInt32 objptr, int fEnable, int fOutputCenter, int fBassToSides);


        [System::Runtime::InteropServices::DllImport("libzplay.dll", EntryPoint="zplay_SetEchoParam", ExactSpelling=true, CharSet=System::Runtime::InteropServices::CharSet::Ansi, SetLastError=true)]
        static int zplay_SetEchoParam(System::UInt32 objptr, [In()] array<TEchoEffect> ^pEchoEffect, int nNumberOfEffects);

        [System::Runtime::InteropServices::DllImport("libzplay.dll", EntryPoint="zplay_GetEchoParam", ExactSpelling=true, CharSet=System::Runtime::InteropServices::CharSet::Ansi, SetLastError=true)]
        static int zplay_GetEchoParam(System::UInt32 objptr, [In(), Out()] array<TEchoEffect> ^pEchoEffect, int nNumberOfEffects);

        [System::Runtime::InteropServices::DllImport("libzplay.dll", EntryPoint="zplay_GetFFTData", ExactSpelling=true, CharSet=System::Runtime::InteropServices::CharSet::Ansi, SetLastError=true)]
        static int zplay_GetFFTData(System::UInt32 objptr, int nFFTPoints, int nFFTWindow, int %pnHarmonicNumber, [In(), Out()] array<int> ^pnHarmonicFreq, [In(), Out()] array<int> ^pnLeftAmplitude, [In(), Out()] array<int> ^pnRightAmplitude, [In(), Out()] array<int> ^pnLeftPhase, [In(), Out()] array<int> ^pnRightPhase);

        [System::Runtime::InteropServices::DllImport("libzplay.dll", EntryPoint="zplay_SetRate", ExactSpelling=true, CharSet=System::Runtime::InteropServices::CharSet::Ansi, SetLastError=true)]
        static int zplay_SetRate(System::UInt32 objptr, int nRate);

        [System::Runtime::InteropServices::DllImport("libzplay.dll", EntryPoint="zplay_GetRate", ExactSpelling=true, CharSet=System::Runtime::InteropServices::CharSet::Ansi, SetLastError=true)]
        static int zplay_GetRate(System::UInt32 objptr);

        [System::Runtime::InteropServices::DllImport("libzplay.dll", EntryPoint="zplay_SetPitch", ExactSpelling=true, CharSet=System::Runtime::InteropServices::CharSet::Ansi, SetLastError=true)]
        static int zplay_SetPitch(System::UInt32 objptr, int nPitch);

        [System::Runtime::InteropServices::DllImport("libzplay.dll", EntryPoint="zplay_GetPitch", ExactSpelling=true, CharSet=System::Runtime::InteropServices::CharSet::Ansi, SetLastError=true)]
        static int zplay_GetPitch(System::UInt32 objptr);

        [System::Runtime::InteropServices::DllImport("libzplay.dll", EntryPoint="zplay_SetTempo", ExactSpelling=true, CharSet=System::Runtime::InteropServices::CharSet::Ansi, SetLastError=true)]
        static int zplay_SetTempo(System::UInt32 objptr, int nTempo);

        [System::Runtime::InteropServices::DllImport("libzplay.dll", EntryPoint="zplay_GetTempo", ExactSpelling=true, CharSet=System::Runtime::InteropServices::CharSet::Ansi, SetLastError=true)]
        static int zplay_GetTempo(System::UInt32 objptr);

        [System::Runtime::InteropServices::DllImport("libzplay.dll", EntryPoint="zplay_DrawFFTGraphOnHDC", ExactSpelling=true, CharSet=System::Runtime::InteropServices::CharSet::Ansi, SetLastError=true)]
        static int zplay_DrawFFTGraphOnHDC(System::UInt32 objptr, System::IntPtr hdc, int nX, int nY, int nWidth, int nHeight);

        [System::Runtime::InteropServices::DllImport("libzplay.dll", EntryPoint="zplay_DrawFFTGraphOnHWND", ExactSpelling=true, CharSet=System::Runtime::InteropServices::CharSet::Ansi, SetLastError=true)]
        static int zplay_DrawFFTGraphOnHWND(System::UInt32 objptr, System::IntPtr hwnd, int nX, int nY, int nWidth, int nHeight);

        [System::Runtime::InteropServices::DllImport("libzplay.dll", EntryPoint="zplay_SetFFTGraphParam", ExactSpelling=true, CharSet=System::Runtime::InteropServices::CharSet::Ansi, SetLastError=true)]
        static int zplay_SetFFTGraphParam(System::UInt32 objptr, int nParamID, int nParamValue);

        [System::Runtime::InteropServices::DllImport("libzplay.dll", EntryPoint="zplay_GetFFTGraphParam", ExactSpelling=true, CharSet=System::Runtime::InteropServices::CharSet::Ansi, SetLastError=true)]
        static int zplay_GetFFTGraphParam(System::UInt32 objptr, int nParamID);


        [System::Runtime::InteropServices::DllImport("libzplay.dll", EntryPoint="zplay_LoadID3W", ExactSpelling=true, CharSet=System::Runtime::InteropServices::CharSet::Ansi, SetLastError=true)]
        static int zplay_LoadID3W(System::UInt32 objptr, int nId3Version, TID3Info_Internal %pId3Info);


		[System::Runtime::InteropServices::DllImport("libzplay.dll", EntryPoint = "zplay_LoadID3ExW", ExactSpelling = true, CharSet = System::Runtime::InteropServices::CharSet::Ansi, SetLastError = true)]
		static int zplay_LoadID3ExW(System::UInt32 objptr, TID3InfoEx_Internal %pId3Info, int fDecodeEmbededPicture);

        [System::Runtime::InteropServices::DllImport("libzplay.dll", EntryPoint="zplay_LoadFileID3W", ExactSpelling=true, CharSet=System::Runtime::InteropServices::CharSet::Unicode, SetLastError=true)]
        static int zplay_LoadFileID3W(System::UInt32 objptr, [MarshalAs(UnmanagedType::LPWStr)] System::String ^pchFileName, int nFormat, int nId3Version, TID3Info_Internal %pId3Info);

	  [System::Runtime::InteropServices::DllImport("libzplay.dll", EntryPoint = "zplay_LoadFileID3ExW", ExactSpelling = true, CharSet = System::Runtime::InteropServices::CharSet::Unicode, SetLastError = true)]
	  static int zplay_LoadFileID3ExW(System::UInt32 objptr, [MarshalAs(UnmanagedType::LPWStr)] System::String ^pchFileName, int nFormat, TID3InfoEx_Internal %pId3Info, int fDecodeEmbededPicture);


        [System::Runtime::InteropServices::DllImport("libzplay.dll", EntryPoint="zplay_DetectBPM", ExactSpelling=true, CharSet=System::Runtime::InteropServices::CharSet::Ansi, SetLastError=true)]
        static int zplay_DetectBPM(System::UInt32 objptr, System::UInt32 nMethod);

        [System::Runtime::InteropServices::DllImport("libzplay.dll", EntryPoint="zplay_DetectFileBPM", ExactSpelling=true, CharSet=System::Runtime::InteropServices::CharSet::Ansi, SetLastError=true)]
        static int zplay_DetectFileBPM(System::UInt32 objptr, [MarshalAs(UnmanagedType::LPStr)] System::String ^sFileName, int nFormat, System::UInt32 nMethod);

        [System::Runtime::InteropServices::DllImport("libzplay.dll", EntryPoint="zplay_DetectFileBPMW", ExactSpelling=true, CharSet=System::Runtime::InteropServices::CharSet::Unicode, SetLastError=true)]
        static int zplay_DetectFileBPMW(System::UInt32 objptr, [MarshalAs(UnmanagedType::LPWStr)] System::String ^sFileName, int nFormat, System::UInt32 nMethod);

        [System::Runtime::InteropServices::DllImport("libzplay.dll", EntryPoint="zplay_SetCallbackFunc", ExactSpelling=true, CharSet=System::Runtime::InteropServices::CharSet::Ansi, SetLastError=true)]
        static int zplay_SetCallbackFunc(System::UInt32 objptr, [MarshalAs(UnmanagedType::FunctionPtr)] TCallbackFunc ^pCallbackFunc, TCallbackMessage nMessage, int user_data);

        [System::Runtime::InteropServices::DllImport("libzplay.dll", EntryPoint="zplay_EnumerateWaveOut", ExactSpelling=true, CharSet=System::Runtime::InteropServices::CharSet::Ansi, SetLastError=true)]
        static int zplay_EnumerateWaveOut(System::UInt32 objptr);

        [System::Runtime::InteropServices::DllImport("libzplay.dll", EntryPoint="zplay_GetWaveOutInfoW", ExactSpelling=true, CharSet=System::Runtime::InteropServices::CharSet::Ansi, SetLastError=true)]
        static int zplay_GetWaveOutInfoW(System::UInt32 objptr, System::UInt32 nIndex, TWaveOutInfo_Internal %pWaveOutInfo);


        [System::Runtime::InteropServices::DllImport("libzplay.dll", EntryPoint="zplay_SetWaveOutDevice", ExactSpelling=true, CharSet=System::Runtime::InteropServices::CharSet::Ansi, SetLastError=true)]
        static int zplay_SetWaveOutDevice(System::UInt32 objptr, System::UInt32 nIndex);



		 [System::Runtime::InteropServices::DllImport("libzplay.dll", EntryPoint="zplay_EnumerateWaveIn", ExactSpelling=true, CharSet=System::Runtime::InteropServices::CharSet::Ansi, SetLastError=true)]
        static int zplay_EnumerateWaveIn(System::UInt32 objptr);


        [System::Runtime::InteropServices::DllImport("libzplay.dll", EntryPoint="zplay_GetWaveInInfoW", ExactSpelling=true, CharSet=System::Runtime::InteropServices::CharSet::Ansi, SetLastError=true)]
        static int zplay_GetWaveInInfoW(System::UInt32 objptr, System::UInt32 nIndex, TWaveInInfo_Internal %pWaveInInfo);


        [System::Runtime::InteropServices::DllImport("libzplay.dll", EntryPoint="zplay_SetWaveInDevice(", ExactSpelling=true, CharSet=System::Runtime::InteropServices::CharSet::Ansi, SetLastError=true)]
        static int zplay_SetWaveInDevice(System::UInt32 objptr, System::UInt32 nIndex);



        [System::Runtime::InteropServices::DllImport("libzplay.dll", EntryPoint="zplay_GetStreamInfoW", ExactSpelling=true, CharSet=System::Runtime::InteropServices::CharSet::Ansi, SetLastError=true)]
        static void zplay_GetStreamInfoW(System::UInt32 objptr, TStreamInfo_Internal %pInfo);


		 [System::Runtime::InteropServices::DllImport("libzplay.dll", EntryPoint="zplay_SetWaveOutFileW", ExactSpelling=true, CharSet=System::Runtime::InteropServices::CharSet::Unicode, SetLastError=true)]
        static int zplay_SetWaveOutFileW(System::UInt32 objptr, [MarshalAs(UnmanagedType::LPWStr)] System::String ^sFileName, int nFormat, int fOutputToSoundcard);



#pragma endregion

#pragma region Members

#pragma endregion

#pragma region Helper functions

        System::UInt32 objptr;

#pragma endregion

#pragma region Constructor and destructor

    public:
        ZPlay()
        {
            objptr = zplay_CreateZPlay();
            if (objptr == 0)
            {
                throw gcnew Exception("Can't create libZPlay interface.");
            }

			if(GetVersion() < 190)
                throw gcnew Exception("Need libZPlay.dll version 1.90 and above.");
        }

    private protected:
        ~ZPlay()
        {
            zplay_DestroyZPlay(objptr);
        }
#pragma endregion

#pragma region Version
    public:
        int GetVersion()
        {
            return zplay_GetVersion(objptr);
        }

#pragma endregion

#pragma region Error handling
        System::String ^GetError()
        {
            return Marshal::PtrToStringUni(zplay_GetErrorW(objptr));
        }

#pragma endregion

#pragma region Open and close stream

        TStreamFormat GetFileFormat(System::String ^FileName)
        {
            return safe_cast<TStreamFormat>(zplay_GetFileFormatW(objptr, FileName));
        }

        bool OpenFile(System::String ^FileName, TStreamFormat Format)
        {
            return zplay_OpenFileW(objptr, FileName, System::Convert::ToInt32(Format)) == 1;
        }

		 bool SetWaveOutFile(System::String ^FileName, TStreamFormat Format, bool fOutputToSoundcard)
        {
				int s = 0;
				if(fOutputToSoundcard)
					s = 1;

            return zplay_SetWaveOutFileW(objptr, FileName, System::Convert::ToInt32(Format), s) == 1;
        }


        bool AddFile(System::String ^FileName, TStreamFormat Format)
        {
            return zplay_AddFileW(objptr, FileName, System::Convert::ToInt32(Format)) == 1;
        }


        bool OpenStream(bool Buffered, bool Dynamic, array<System::Byte> ^%MemStream, System::UInt32 StreamSize, TStreamFormat nFormat)
        {
            int b = 0;
            int m = 0;
            if (Buffered)
            {
                b = 1;
            }
            if (Dynamic)
            {
                m = 1;
            }
            return zplay_OpenStream(objptr, b, m, MemStream, StreamSize, System::Convert::ToInt32(nFormat)) == 1;
        }


        bool PushDataToStream(array<System::Byte> ^%MemNewData, System::UInt32 NewDatSize)
        {
            return zplay_PushDataToStream(objptr, MemNewData, NewDatSize) == 1;
        }

        bool IsStreamDataFree(array<System::Byte> ^%MemNewData)
        {
            return zplay_IsStreamDataFree(objptr, MemNewData) == 1;
        }

        bool Close()
        {
            return zplay_Close(objptr) == 1;
        }

#pragma endregion

#pragma region Position and Seek


        void GetPosition(TStreamTime %time)
        {
            zplay_GetPosition(objptr, time);
        }

        bool Seek(TTimeFormat TimeFormat, TStreamTime %Position, TSeekMethod MoveMethod)
        {
            return zplay_Seek(objptr, TimeFormat, Position, MoveMethod) == 1;
        }



#pragma endregion

#pragma region Play, Pause, Loop, Reverse



        bool ReverseMode(bool Enable)
        {
            if (Enable)
            {
                return zplay_ReverseMode(objptr, 1) == 1;
            }
            else
            {
                return zplay_ReverseMode(objptr, 0) == 1;
            }

        }

        bool PlayLoop(TTimeFormat TimeFormatStart, TStreamTime %StartPosition, TTimeFormat TimeFormatEnd, TStreamTime %EndPosition, System::UInt32 NumberOfCycles, bool ContinuePlaying)
        {
            System::UInt32 continueplay = 0;
            if (ContinuePlaying)
            {
                continueplay = 1;
            }
            else
            {
                continueplay = 0;
            }

            return zplay_PlayLoop(objptr, System::Convert::ToInt32(safe_cast<int>(TimeFormatStart)), StartPosition, System::Convert::ToInt32(safe_cast<int>(TimeFormatEnd)), EndPosition, NumberOfCycles, continueplay) == 1;
        }

        bool StartPlayback()
        {
            return zplay_Play(objptr) == 1;
        }

        bool StopPlayback()
        {
            return zplay_Stop(objptr) == 1;
        }

        bool PausePlayback()
        {
            return zplay_Pause(objptr) == 1;
        }

        bool ResumePlayback()
        {
            return zplay_Resume(objptr) == 1;
        }


#pragma endregion

#pragma region Equalizer


        bool SetEqualizerParam(int PreAmpGain, array<int> ^%BandGain, int NumberOfBands)
        {
            return zplay_SetEqualizerParam(objptr, PreAmpGain, BandGain, NumberOfBands) == 1;
        }


        int GetEqualizerParam(int %PreAmpGain, array<int> ^%BandGain)
        {
            int tempnPreAmpGain1 = 0;
            int size = zplay_GetEqualizerParam(objptr, tempnPreAmpGain1, nullptr, 0);
            Array::Resize(BandGain, size);
            return zplay_GetEqualizerParam(objptr, PreAmpGain, BandGain, size);
        }



        bool EnableEqualizer(bool Enable)
        {
            if (Enable)
            {
                return zplay_EnableEqualizer(objptr, 1) == 1;
            }
            return zplay_EnableEqualizer(objptr, 0) == 1;
        }

        bool SetEqualizerPreampGain(int Gain)
        {
            return zplay_SetEqualizerPreampGain(objptr, Gain) == 1;
        }

        int GetEqualizerPreampGain()
        {
            return zplay_GetEqualizerPreampGain(objptr);
        }

        bool SetEqualizerBandGain(int BandIndex, int Gain)
        {
            return zplay_SetEqualizerBandGain(objptr, BandIndex, Gain) == 1;
        }

        int GetEqualizerBandGain(int BandIndex)
        {
            return zplay_GetEqualizerBandGain(objptr, BandIndex);
        }

        bool SetEqualizerPoints(array<int> ^%FreqPointArray, int NumberOfPoints)
        {
            return zplay_SetEqualizerPoints(objptr, FreqPointArray, NumberOfPoints) == 1;
        }

        int GetEqualizerPoints(array<int> ^%FreqPointArray)
        {
            int size = zplay_GetEqualizerPoints(objptr, nullptr, 0);
            Array::Resize(FreqPointArray, size);
            return zplay_GetEqualizerPoints(objptr, FreqPointArray, size);
        }
#pragma endregion

#pragma region Echo


        bool EnableEcho(bool Enable)
        {
            if (Enable)
            {
                return zplay_EnableEcho(objptr, 1) == 1;
            }
            return zplay_EnableEcho(objptr, 0) == 1;
        }


        bool SetEchoParam(array<TEchoEffect> ^%EchoEffectArray, int NumberOfEffects)
        {
            return zplay_SetEchoParam(objptr, EchoEffectArray, NumberOfEffects) == 1;
        }

        int GetEchoParam(array<TEchoEffect> ^%EchoEffectArray)
        {
            int size = zplay_GetEchoParam(objptr, nullptr, 0);
            Array::Resize(EchoEffectArray, size);
            return zplay_GetEchoParam(objptr, EchoEffectArray, size);
        }
#pragma endregion

#pragma region Volume and Fade
        bool SetMasterVolume(int LeftVolume, int RightVolume)
        {
            return zplay_SetMasterVolume(objptr, LeftVolume, RightVolume) == 1;
        }

        bool SetPlayerVolume(int LeftVolume, int RightVolume)
        {
            return zplay_SetPlayerVolume(objptr, LeftVolume, RightVolume) == 1;
        }


        void GetMasterVolume(int %LeftVolume, int %RightVolume)
        {
            zplay_GetMasterVolume(objptr, LeftVolume, RightVolume);
        }

        void GetPlayerVolume(int %LeftVolume, int %RightVolume)
        {
            zplay_GetPlayerVolume(objptr, LeftVolume, RightVolume);
        }




        bool SlideVolume(TTimeFormat TimeFormatStart, TStreamTime %TimeStart, int StartVolumeLeft, int StartVolumeRight, TTimeFormat TimeFormatEnd, TStreamTime %TimeEnd, int EndVolumeLeft, int EndVolumeRight)
        {
            return zplay_SlideVolume(objptr, TimeFormatStart, TimeStart, StartVolumeLeft, StartVolumeRight, TimeFormatEnd, TimeEnd, EndVolumeLeft, EndVolumeRight) == 1;
        }


#pragma endregion

#pragma region Pitch, tempo, rate
        bool SetPitch(int Pitch)
        {
            return zplay_SetPitch(objptr, Pitch) == 1;
        }

        int GetPitch()
        {
            return zplay_GetPitch(objptr);
        }

        bool SetRate(int Rate)
        {
            return zplay_SetRate(objptr, Rate) == 1;
        }

        int GetRate()
        {
            return zplay_GetRate(objptr);
        }

        bool SetTempo(int Tempo)
        {
            return zplay_SetTempo(objptr, Tempo) == 1;
        }

        int GetTempo()
        {
            return zplay_GetTempo(objptr);
        }


#pragma endregion

#pragma region Bitrate
        int GetBitrate(bool Average)
        {
            if(Average)
                return zplay_GetBitrate(objptr, 1);
            else
                return zplay_GetBitrate(objptr, 0);
        }



#pragma endregion

#pragma region ID3 Info

        bool LoadID3(TID3Version Id3Version, TID3Info %Info)
        {
			TID3Info_Internal tmp;
            if (zplay_LoadID3W(objptr, System::Convert::ToInt32(safe_cast<int>(Id3Version)), tmp) == 1)
            {
				Info.Album = Marshal::PtrToStringUni(tmp.Album);
                Info.Artist = Marshal::PtrToStringUni(tmp.Artist);
                Info.Comment = Marshal::PtrToStringUni(tmp.Comment);
                Info.Genre = Marshal::PtrToStringUni(tmp.Genre);
                Info.Title = Marshal::PtrToStringUni(tmp.Title);
                Info.Track = Marshal::PtrToStringUni(tmp.Track);
                Info.Year = Marshal::PtrToStringUni(tmp.Year);
                return true;
            }
            else
            {
                return false;
            }
        }



		bool LoadID3Ex(TID3InfoEx %Info, bool fDecodePicture)
		{
			TID3InfoEx_Internal tmp;

			if (zplay_LoadID3ExW(objptr, tmp, 0) == 1)
			{
				Info.Album = Marshal::PtrToStringUni(tmp.Album);
				Info.Artist = Marshal::PtrToStringUni(tmp.Artist);
				Info.Comment = Marshal::PtrToStringUni(tmp.Comment);
				Info.Genre = Marshal::PtrToStringUni(tmp.Genre);
				Info.Title = Marshal::PtrToStringUni(tmp.Title);
				Info.Track = Marshal::PtrToStringUni(tmp.Track);
				Info.Year = Marshal::PtrToStringUni(tmp.Year);

				Info.AlbumArtist = Marshal::PtrToStringUni(tmp.AlbumArtist);
				Info.Composer = Marshal::PtrToStringUni(tmp.Composer);
				Info.OriginalArtist = Marshal::PtrToStringUni(tmp.OriginalArtist);
				Info.Copyright = Marshal::PtrToStringUni(tmp.Copyright);
				Info.Encoder = Marshal::PtrToStringUni(tmp.Encoder);
				Info.Publisher = Marshal::PtrToStringUni(tmp.Publisher);
				Info.BPM = tmp.BPM;

				Info.Picture.PicturePresent = false;
				if (fDecodePicture)
				{
					try
					{
						if (tmp.PicturePresent == 1)
						{
							array<System::Byte> ^stream_data = gcnew array<System::Byte>(System::Convert::ToInt32(tmp.PictureDataSize) + 1);
							Marshal::Copy(tmp.PictureData, stream_data, 0, tmp.PictureDataSize);
							Info.Picture.BitStream = gcnew System::IO::MemoryStream();
							Info.Picture.BitStream->Write(stream_data, 0, tmp.PictureDataSize);
							Info.Picture.Bitmap = gcnew Bitmap(Info.Picture.BitStream);
							Info.Picture.PictureType = tmp.PictureType;
							Info.Picture.Description = Marshal::PtrToStringUni(tmp.Description);
							Info.Picture.PicturePresent = true;
						}
						else
						{
							Info.Picture.Bitmap = gcnew Bitmap(1, 1);
						}
						return true;

					}
					catch(...)
					{
						Info.Picture.PicturePresent = false;
					}
				}
			


			}
			else
			{
				return false;
			}

			return false;
		}


        bool LoadFileID3(System::String ^FileName, TStreamFormat Format, TID3Version Id3Version, TID3Info %Info)
        {
			TID3Info_Internal tmp;
            if (zplay_LoadFileID3W(objptr, FileName, System::Convert::ToInt32(Format), System::Convert::ToInt32(safe_cast<int>(Id3Version)), tmp) == 1)
            {
				Info.Album = Marshal::PtrToStringUni(tmp.Album);
                Info.Artist = Marshal::PtrToStringUni(tmp.Artist);
                Info.Comment = Marshal::PtrToStringUni(tmp.Comment);
                Info.Genre = Marshal::PtrToStringUni(tmp.Genre);
                Info.Title = Marshal::PtrToStringUni(tmp.Title);
                Info.Track = Marshal::PtrToStringUni(tmp.Track);
                Info.Year = Marshal::PtrToStringUni(tmp.Year);
                return true;
            }
            else
            {
                return false;
            }
        }

		bool LoadFileID3Ex(System::String ^FileName, TStreamFormat Format,TID3InfoEx %Info, bool fDecodePicture)
		{
			TID3InfoEx_Internal tmp;

			if (zplay_LoadFileID3ExW(objptr, FileName, System::Convert::ToInt32(Format), tmp, 0) == 1)
			{
				Info.Album = Marshal::PtrToStringUni(tmp.Album);
				Info.Artist = Marshal::PtrToStringUni(tmp.Artist);
				Info.Comment = Marshal::PtrToStringUni(tmp.Comment);
				Info.Genre = Marshal::PtrToStringUni(tmp.Genre);
				Info.Title = Marshal::PtrToStringUni(tmp.Title);
				Info.Track = Marshal::PtrToStringUni(tmp.Track);
				Info.Year = Marshal::PtrToStringUni(tmp.Year);

				Info.AlbumArtist = Marshal::PtrToStringUni(tmp.AlbumArtist);
				Info.Composer = Marshal::PtrToStringUni(tmp.Composer);
				Info.OriginalArtist = Marshal::PtrToStringUni(tmp.OriginalArtist);
				Info.Copyright = Marshal::PtrToStringUni(tmp.Copyright);
				Info.Encoder = Marshal::PtrToStringUni(tmp.Encoder);
				Info.Publisher = Marshal::PtrToStringUni(tmp.Publisher);
				Info.BPM = tmp.BPM;

				Info.Picture.PicturePresent = false;
				if (fDecodePicture)
				{
					try
					{
						if (tmp.PicturePresent == 1)
						{
							array<System::Byte> ^stream_data = gcnew array<System::Byte>(System::Convert::ToInt32(tmp.PictureDataSize) + 1);
							Marshal::Copy(tmp.PictureData, stream_data, 0, tmp.PictureDataSize);
							Info.Picture.BitStream = gcnew System::IO::MemoryStream();
							Info.Picture.BitStream->Write(stream_data, 0, tmp.PictureDataSize);
							Info.Picture.Bitmap = gcnew Bitmap(Info.Picture.BitStream);
							Info.Picture.PictureType = tmp.PictureType;
							Info.Picture.Description = Marshal::PtrToStringUni(tmp.Description);
							Info.Picture.PicturePresent = true;
						}
						else
						{
							Info.Picture.Bitmap = gcnew Bitmap(1, 1);
						}
						return true;

					}
					catch(...)
					{
						Info.Picture.PicturePresent = false;
					}
				}
			}
			else
			{
				return false;
			}

			return false;
		}



#pragma endregion

#pragma region Callback
        bool SetCallbackFunc(TCallbackFunc ^CallbackFunc, TCallbackMessage Messages, int UserData)
        {
            return zplay_SetCallbackFunc(objptr, CallbackFunc, Messages, UserData) == 1;
        }
#pragma endregion

#pragma region Beat-Per-Minute
        int DetectBPM(TBPMDetectionMethod Method)
        {
            return zplay_DetectBPM(objptr, System::Convert::ToUInt32(Method));
        }

        int DetectFileBPM(System::String ^FileName, TStreamFormat Format, TBPMDetectionMethod Method)
        {
            return zplay_DetectFileBPMW(objptr, FileName, System::Convert::ToInt32(Format), System::Convert::ToUInt32(Method));
        }
#pragma endregion

#pragma region FFT Graph and FFT values


        bool GetFFTData(int FFTPoints, TFFTWindow FFTWindow, int %HarmonicNumber, array<int> ^%HarmonicFreq, array<int> ^%LeftAmplitude, array<int> ^%RightAmplitude, array<int> ^%LeftPhase, array<int> ^%RightPhase)
        {
            return zplay_GetFFTData(objptr, FFTPoints, System::Convert::ToInt32(safe_cast<int>(FFTWindow)), HarmonicNumber, HarmonicFreq, LeftAmplitude, RightAmplitude, LeftPhase, RightPhase) == 1;
        }

        bool DrawFFTGraphOnHDC(System::IntPtr hdc, int X, int Y, int Width, int Height)
        {
            return zplay_DrawFFTGraphOnHDC(objptr, hdc, X, Y, Width, Height) == 1;
        }

        bool DrawFFTGraphOnHWND(System::IntPtr hwnd, int X, int Y, int Width, int Height)
        {
            return zplay_DrawFFTGraphOnHWND(objptr, hwnd, X, Y, Width, Height) == 1;
        }


        bool SetFFTGraphParam(TFFTGraphParamID ParamID, int ParamValue)
        {
            return zplay_SetFFTGraphParam(objptr, System::Convert::ToInt32(safe_cast<int>(ParamID)), ParamValue) == 1;
        }

        int GetFFTGraphParam(TFFTGraphParamID ParamID)
        {
            return zplay_GetFFTGraphParam(objptr, System::Convert::ToInt32(safe_cast<int>(ParamID)));
        }

    

        
#pragma endregion

#pragma region Center and side cut

        bool StereoCut(bool Enable, bool OutputCenter, bool BassToSides)
        {
            int fOutputCenter = 0;
            int fBassToSides = 0;
            int fEnable = 0;
            if (OutputCenter)
            {
                fOutputCenter = 1;
            }
            if (BassToSides)
            {
                fBassToSides = 1;
            }
            if (Enable)
            {
                fEnable = 1;
            }
            return zplay_StereoCut(objptr, fEnable, fOutputCenter, fBassToSides) == 1;
        }



#pragma endregion

#pragma region Channel mixing


        bool MixChannels(bool Enable, System::UInt32 LeftPercent, System::UInt32 RightPercent)
        {
            if (Enable)
            {
                return zplay_MixChannels(objptr, 1, LeftPercent, RightPercent) == 1;
            }
            else
            {
                return zplay_MixChannels(objptr, 0, LeftPercent, RightPercent) == 1;
            }

        }
#pragma endregion

#pragma region VU Data

        void GetVUData(int %LeftChannel, int %RightChannel)
        {
            zplay_GetVUData(objptr, LeftChannel, RightChannel);
        }

#pragma endregion

#pragma region Status and Info

        void GetStreamInfo(TStreamInfo %info)
        {
			TStreamInfo_Internal tmp;
            zplay_GetStreamInfoW(objptr, tmp);
			info.Bitrate = tmp.Bitrate;
            info.ChannelNumber = tmp.ChannelNumber;
            info.SamplingRate = tmp.SamplingRate;
            info.VBR = tmp.VBR;
            info.Length = tmp.Length;
			info.Description = Marshal::PtrToStringUni(tmp.Description);
        }

        void GetStatus(TStreamStatus %status)
        {
            zplay_GetStatus(objptr, status);
        }

        void GetDynamicStreamLoad(TStreamLoadInfo %StreamLoadInfo)
        {
            zplay_GetDynamicStreamLoad(objptr, StreamLoadInfo);
        }
#pragma endregion

#pragma region Wave Out and Wave In Info

        int EnumerateWaveOut()
        {
            return zplay_EnumerateWaveOut(objptr);
        }

        bool GetWaveOutInfo(System::UInt32 Index, TWaveOutInfo %Info)
        {
			TWaveOutInfo_Internal tmp;
            if (zplay_GetWaveOutInfoW(objptr, Index, tmp) == 0)
            {
                return false;
            }
			Info.Channels = tmp.Channels;
            Info.DriverVersion = tmp.DriverVersion;
            Info.Formats = tmp.Formats;
            Info.ManufacturerID = tmp.ManufacturerID;
            Info.ProductID = tmp.ProductID;
            Info.Support = tmp.Support;
			Info.ProductName = Marshal::PtrToStringUni(tmp.ProductName);
            return true;
        }

        bool SetWaveOutDevice(System::UInt32 Index)
        {
            return zplay_SetWaveOutDevice(objptr, Index) == 1;
        }


		int EnumerateWaveIn()
        {
            return zplay_EnumerateWaveIn(objptr);
        }

        bool GetWaveInInfo(System::UInt32 Index, TWaveInInfo %Info)
        {
			TWaveInInfo_Internal tmp;
            if (zplay_GetWaveInInfoW(objptr, Index, tmp) == 0)
            {
                return false;
            }
			Info.Channels = tmp.Channels;
            Info.DriverVersion = tmp.DriverVersion;
            Info.Formats = tmp.Formats;
            Info.ManufacturerID = tmp.ManufacturerID;
            Info.ProductID = tmp.ProductID;
			Info.ProductName = Marshal::PtrToStringUni(tmp.ProductName);
            return true;
        }

        bool SetWaveInDevice(System::UInt32 Index)
        {
            return zplay_SetWaveInDevice(objptr, Index) == 1;
        }

#pragma endregion


#pragma region Settings

        int SetSettings(TSettingID SettingID, int Value)
        {
            return zplay_SetSettings(objptr, (int) SettingID, Value);
        }


        int GetSettings(TSettingID SettingID)
        {
            return zplay_GetSettings(objptr, (int) SettingID);
        }

#pragma endregion

    };

}